package io.onedev.server.web.page.admin.gpgsigningkey;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.model.Model;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.bouncycastle.bcpg.ArmoredOutputStream;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPKeyRingGenerator;
import org.bouncycastle.openpgp.PGPSecretKeyRing;

import io.onedev.commons.utils.StringUtils;
import io.onedev.server.OneDev;
import io.onedev.server.entitymanager.SettingManager;
import io.onedev.server.model.User;
import io.onedev.server.model.support.administration.GpgSetting;
import io.onedev.server.util.GpgUtils;
import io.onedev.server.web.component.link.copytoclipboard.CopyToClipboardLink;
import io.onedev.server.web.component.modal.confirm.ConfirmModalPanel;
import io.onedev.server.web.page.admin.AdministrationPage;

@SuppressWarnings("serial")
public class GpgSigningKeyPage extends AdministrationPage {

	public GpgSigningKeyPage(PageParameters params) {
		super(params);
	}

	@Override
	protected void onInitialize() {
		super.onInitialize();
		
		GpgSetting setting = getSettingManager().getGpgSetting();
		PGPSecretKeyRing signingKey = setting.getSigningKey();
		if (signingKey != null) {
			Fragment fragment = new Fragment("content", "definedFrag", this);
			fragment.add(new Label("keyID", GpgUtils.getKeyIDString(signingKey.getPublicKey().getKeyID())));
			fragment.add(new Label("emailAddress", StringUtils.join(GpgUtils.getEmailAddresses(signingKey.getPublicKey()), ", ")));
			
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			try (ArmoredOutputStream aos = new ArmoredOutputStream(baos)) {
				signingKey.getPublicKey().encode(aos);
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
			
			String publicKey = new String(baos.toByteArray());
			fragment.add(new Label("publicKey", publicKey));
			fragment.add(new CopyToClipboardLink("copyPublicKey", Model.of(publicKey)));
			
	    	fragment.add(new AjaxLink<Void>("delete") {

				@Override
				public void onClick(AjaxRequestTarget target) {
					new ConfirmModalPanel(target) {
						
						@Override
						protected void onConfirm(AjaxRequestTarget target) {
							GpgSetting setting = getSettingManager().getGpgSetting();
						    setting.setEncodedSigningKey(null);
						    getSettingManager().saveGpgSetting(setting);
							setResponsePage(GpgSigningKeyPage.class);
						}
						
						@Override
						protected String getConfirmMessage() {
							return "Commits generated by OneDev previously will be shown as unverified if this key is deleted. "
									+ "Type <code>yes</code> below if you want to continue.";						
						}
						
						@Override
						protected String getConfirmInput() {
							return "yes";
						}
						
					};
				}

	    	});
			
			add(fragment);
		} else {
			Fragment fragment = new Fragment("content", "undefinedFrag", this);
			fragment.add(new AjaxLink<Void>("generate") {

				@Override
				public void onClick(AjaxRequestTarget target) {
					ByteArrayOutputStream baos;
					try {
						PGPKeyRingGenerator generator = GpgUtils.generateKeyRingGenerator(
								User.SYSTEM_NAME + "<" + User.SYSTEM_EMAIL_ADDRESS + ">");
						
						PGPSecretKeyRing secretKeyRing = generator.generateSecretKeyRing();
						baos = new ByteArrayOutputStream();
						secretKeyRing.encode(baos);
					} catch (PGPException | IOException e) {
						throw new RuntimeException(e);
					}

					GpgSetting setting = getSettingManager().getGpgSetting();
				    setting.setEncodedSigningKey(baos.toByteArray());
				    getSettingManager().saveGpgSetting(setting);
					setResponsePage(GpgSigningKeyPage.class);
				}

			});
			add(fragment);
		}
	}
	
	private SettingManager getSettingManager() {
		return OneDev.getInstance(SettingManager.class);
	}

	@Override
	protected Component newTopbarTitle(String componentId) {
		return new Label(componentId, "GPG Signing Key");
	}

}
